using Microsoft.EntityFrameworkCore;
using SheLife.Domain.Entities;
using SheLife.Domain.Interfaces.Repositories;
using SheLife.Infrastructure.Data;

namespace SheLife.Infrastructure.Repositories
{
    public class SystemConfigRepository : Repository<SystemConfig>, ISystemConfigRepository
    {
        public SystemConfigRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<SystemConfig> GetByKeyAsync(string key)
        {
            return await _dbSet
                .Where(s => s.Key == key)
                .FirstOrDefaultAsync();
        }

        public async Task<IEnumerable<SystemConfig>> GetByCategoryAsync(string category)
        {
            return await _dbSet
                .Where(s => s.Category == category)
                .OrderBy(s => s.Key)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemConfig>> GetActiveConfigsAsync()
        {
            return await _dbSet
                .Where(s => s.IsActive)
                .OrderBy(s => s.Category)
                .ThenBy(s => s.Key)
                .ToListAsync();
        }
    }

    public class SystemLogRepository : Repository<SystemLog>, ISystemLogRepository
    {
        public SystemLogRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemLog>> GetByLevelAsync(string level)
        {
            return await _dbSet
                .Where(s => s.Level == level)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemLog>> GetByCategoryAsync(string category)
        {
            return await _dbSet
                .Where(s => s.Category == category)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemLog>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet
                .Where(s => s.UserId == userId)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemLog>> GetByTimeRangeAsync(DateTime startTime, DateTime endTime)
        {
            return await _dbSet
                .Where(s => s.CreatedTime >= startTime && s.CreatedTime <= endTime)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemLog>> GetErrorLogsAsync()
        {
            return await _dbSet
                .Where(s => s.Level == "Error" || s.Level == "Fatal")
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }
    }

    public class SystemNotificationRepository : Repository<SystemNotification>, ISystemNotificationRepository
    {
        public SystemNotificationRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemNotification>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet
                .Where(s => s.UserId == userId)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemNotification>> GetByTypeAsync(string type)
        {
            return await _dbSet
                .Where(s => s.Type == type)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemNotification>> GetByStatusAsync(string status)
        {
            return await _dbSet
                .Where(s => s.Status == status)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemNotification>> GetUnreadNotificationsByUserIdAsync(Guid userId)
        {
            return await _dbSet
                .Where(s => s.UserId == userId && s.Status == "Unread")
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<int> GetUnreadCountByUserIdAsync(Guid userId)
        {
            return await _dbSet
                .CountAsync(s => s.UserId == userId && s.Status == "Unread");
        }
    }

    public class SystemVersionRepository : Repository<SystemVersion>, ISystemVersionRepository
    {
        public SystemVersionRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<SystemVersion> GetLatestVersionAsync()
        {
            return await _dbSet
                .OrderByDescending(s => s.Version)
                .FirstOrDefaultAsync();
        }

        public async Task<SystemVersion> GetByVersionAsync(string version)
        {
            return await _dbSet
                .Where(s => s.Version == version)
                .FirstOrDefaultAsync();
        }

        public async Task<IEnumerable<SystemVersion>> GetByPlatformAsync(string platform)
        {
            return await _dbSet
                .Where(s => s.Platform == platform)
                .OrderByDescending(s => s.Version)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemVersion>> GetByStatusAsync(string status)
        {
            return await _dbSet
                .Where(s => s.Status == status)
                .OrderByDescending(s => s.Version)
                .ToListAsync();
        }
    }

    public class SystemFeedbackRepository : Repository<SystemFeedback>, ISystemFeedbackRepository
    {
        public SystemFeedbackRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemFeedback>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet
                .Where(s => s.UserId == userId)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemFeedback>> GetByTypeAsync(string type)
        {
            return await _dbSet
                .Where(s => s.Type == type)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemFeedback>> GetByStatusAsync(string status)
        {
            return await _dbSet
                .Where(s => s.Status == status)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemFeedback>> GetByTimeRangeAsync(DateTime startTime, DateTime endTime)
        {
            return await _dbSet
                .Where(s => s.CreatedTime >= startTime && s.CreatedTime <= endTime)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }
    }

    public class SystemAnnouncementRepository : Repository<SystemAnnouncement>, ISystemAnnouncementRepository
    {
        public SystemAnnouncementRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemAnnouncement>> GetActiveAnnouncementsAsync()
        {
            return await _dbSet
                .Where(s => s.IsActive && s.StartTime <= DateTime.Now && s.EndTime >= DateTime.Now)
                .OrderByDescending(s => s.Priority)
                .ThenByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemAnnouncement>> GetByTypeAsync(string type)
        {
            return await _dbSet
                .Where(s => s.Type == type)
                .OrderByDescending(s => s.Priority)
                .ThenByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemAnnouncement>> GetByTimeRangeAsync(DateTime startTime, DateTime endTime)
        {
            return await _dbSet
                .Where(s => s.StartTime >= startTime && s.EndTime <= endTime)
                .OrderByDescending(s => s.Priority)
                .ThenByDescending(s => s.CreatedTime)
                .ToListAsync();
        }
    }

    public class SystemPermissionRepository : Repository<SystemPermission>, ISystemPermissionRepository
    {
        public SystemPermissionRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemPermission>> GetByRoleIdAsync(Guid roleId)
        {
            return await _dbSet
                .Where(s => s.RoleId == roleId)
                .OrderBy(s => s.Resource)
                .ThenBy(s => s.Action)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemPermission>> GetByResourceAsync(string resource)
        {
            return await _dbSet
                .Where(s => s.Resource == resource)
                .OrderBy(s => s.Action)
                .ToListAsync();
        }

        public async Task<bool> HasPermissionAsync(Guid roleId, string resource, string action)
        {
            return await _dbSet
                .AnyAsync(s => s.RoleId == roleId && s.Resource == resource && s.Action == action);
        }
    }

    public class SystemRoleRepository : Repository<SystemRole>, ISystemRoleRepository
    {
        public SystemRoleRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<SystemRole> GetByNameAsync(string name)
        {
            return await _dbSet
                .Where(s => s.Name == name)
                .FirstOrDefaultAsync();
        }

        public async Task<IEnumerable<SystemRole>> GetByStatusAsync(string status)
        {
            return await _dbSet
                .Where(s => s.Status == status)
                .OrderBy(s => s.Name)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemRole>> GetActiveRolesAsync()
        {
            return await _dbSet
                .Where(s => s.IsActive)
                .OrderBy(s => s.Name)
                .ToListAsync();
        }
    }

    public class SystemMenuRepository : Repository<SystemMenu>, ISystemMenuRepository
    {
        public SystemMenuRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemMenu>> GetByParentIdAsync(Guid? parentId)
        {
            return await _dbSet
                .Where(s => s.ParentId == parentId)
                .OrderBy(s => s.Order)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemMenu>> GetByRoleIdAsync(Guid roleId)
        {
            return await _dbSet
                .Where(s => s.RoleId == roleId)
                .OrderBy(s => s.Order)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemMenu>> GetActiveMenusAsync()
        {
            return await _dbSet
                .Where(s => s.IsActive)
                .OrderBy(s => s.Order)
                .ToListAsync();
        }

        public async Task<SystemMenu> GetByPathAsync(string path)
        {
            return await _dbSet
                .Where(s => s.Path == path)
                .FirstOrDefaultAsync();
        }
    }

    public class SystemOperationLogRepository : Repository<SystemOperationLog>, ISystemOperationLogRepository
    {
        public SystemOperationLogRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemOperationLog>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet
                .Where(s => s.UserId == userId)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemOperationLog>> GetByModuleAsync(string module)
        {
            return await _dbSet
                .Where(s => s.Module == module)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemOperationLog>> GetByActionAsync(string action)
        {
            return await _dbSet
                .Where(s => s.Action == action)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemOperationLog>> GetByTimeRangeAsync(DateTime startTime, DateTime endTime)
        {
            return await _dbSet
                .Where(s => s.CreatedTime >= startTime && s.CreatedTime <= endTime)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }
    }

    public class SystemExceptionLogRepository : Repository<SystemExceptionLog>, ISystemExceptionLogRepository
    {
        public SystemExceptionLogRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemExceptionLog>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet
                .Where(s => s.UserId == userId)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemExceptionLog>> GetByTypeAsync(string type)
        {
            return await _dbSet
                .Where(s => s.Type == type)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemExceptionLog>> GetByTimeRangeAsync(DateTime startTime, DateTime endTime)
        {
            return await _dbSet
                .Where(s => s.CreatedTime >= startTime && s.CreatedTime <= endTime)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }
    }

    public class SystemTaskRepository : Repository<SystemTask>, ISystemTaskRepository
    {
        public SystemTaskRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemTask>> GetByTypeAsync(string type)
        {
            return await _dbSet
                .Where(s => s.Type == type)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemTask>> GetByStatusAsync(string status)
        {
            return await _dbSet
                .Where(s => s.Status == status)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemTask>> GetByCreatorIdAsync(Guid creatorId)
        {
            return await _dbSet
                .Where(s => s.CreatorId == creatorId)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemTask>> GetByExecutorIdAsync(Guid executorId)
        {
            return await _dbSet
                .Where(s => s.ExecutorId == executorId)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemTask>> GetPendingTasksAsync()
        {
            return await _dbSet
                .Where(s => s.Status == "Pending")
                .OrderBy(s => s.ScheduledTime)
                .ToListAsync();
        }
    }

    public class SystemTaskLogRepository : Repository<SystemTaskLog>, ISystemTaskLogRepository
    {
        public SystemTaskLogRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemTaskLog>> GetByTaskIdAsync(Guid taskId)
        {
            return await _dbSet
                .Where(s => s.TaskId == taskId)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemTaskLog>> GetByStatusAsync(string status)
        {
            return await _dbSet
                .Where(s => s.Status == status)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemTaskLog>> GetByTimeRangeAsync(DateTime startTime, DateTime endTime)
        {
            return await _dbSet
                .Where(s => s.CreatedTime >= startTime && s.CreatedTime <= endTime)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }
    }

    public class SystemDataBackupRepository : Repository<SystemDataBackup>, ISystemDataBackupRepository
    {
        public SystemDataBackupRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemDataBackup>> GetByTypeAsync(string type)
        {
            return await _dbSet
                .Where(s => s.Type == type)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemDataBackup>> GetByStatusAsync(string status)
        {
            return await _dbSet
                .Where(s => s.Status == status)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemDataBackup>> GetByTimeRangeAsync(DateTime startTime, DateTime endTime)
        {
            return await _dbSet
                .Where(s => s.CreatedTime >= startTime && s.CreatedTime <= endTime)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }
    }

    public class SystemDataRestoreRepository : Repository<SystemDataRestore>, ISystemDataRestoreRepository
    {
        public SystemDataRestoreRepository(ApplicationDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemDataRestore>> GetByBackupIdAsync(Guid backupId)
        {
            return await _dbSet
                .Where(s => s.BackupId == backupId)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemDataRestore>> GetByStatusAsync(string status)
        {
            return await _dbSet
                .Where(s => s.Status == status)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemDataRestore>> GetByTimeRangeAsync(DateTime startTime, DateTime endTime)
        {
            return await _dbSet
                .Where(s => s.CreatedTime >= startTime && s.CreatedTime <= endTime)
                .OrderByDescending(s => s.CreatedTime)
                .ToListAsync();
        }
    }
}